// #include "db.hpp"

// #include "online.hpp"

// #include "room.hpp"

// #include "session.hpp"

// #include "matcher.hpp"

#include "server.hpp"

#define HOST "127.0.0.1"    // 设置只能本地登录
#define PORT 3306           // 默认就是3306
#define USER "root"         // root 用户登录
#define PASS "ax020913"     // root 登录 mysql 的密码
#define DBNAME "gobang"     // 我们刚刚创建的 gobang 数据库

void mysql_util(){
    MYSQL* mysql = mysql_util::mysql_create(HOST, USER, PASS, DBNAME, PORT);
    const char* sql = "insert stu value(null, '小明', 18, 53, 68, 87);";
    bool ret = mysql_util::mysql_exec(mysql, sql);
    if(ret == false)
        return;
    mysql_util::mysql_destroy(mysql);
}

void json_util(){
    // 序列化
    // 将需要进行序列化的数据，存储在Json::Value 对象中
    Json::Value root;
    std::string body;
    root["姓名"] = "小敏";
    root["年龄"] = 20;
    // 因为成绩的话有几个学科的成绩，所以是一个数组存储。数组添加元素得用append接口的哦
    root["成绩"].append(89);  
    root["成绩"].append(89.4);
    root["成绩"].append(96);
    json_util::serialize(root, body);
    // DLOG(body.c_str());     // 这样写是有问题的哦
    DLOG("%s", body.c_str());  // DBUG 类型的日志

    // 反序列化
    Json::Value val;
    json_util::unserialize(body, val);
    // 逐个元素去访问Json::Value中的数据
    std::cout << "姓名 " << val["姓名"].asString() << std::endl;
    std::cout << "年龄 " << val["年龄"].asInt() << std::endl;
    int cnt = val["成绩"].size();
    for(int i = 0; i < cnt; i++)
        std::cout << "成绩 " << val["成绩"][i].asFloat() << std::endl;
}


void string_util(){
    std::string str = "123,234,,,,,345,,,,";
    std::string sep = ",";
    std::vector<std::string> array;

    string_util::split(str, sep, array);
    for(auto s: array)
        DLOG("%s", s.c_str());
}

void file_util(){
    std::string filename = "./makefile";
    std::string body;
    bool ret = file_util::read(filename, body);

    std::cout << body << std::endl;
}


void db_test(){
    user_table ut(HOST, USER, PASS, DBNAME, PORT);
    Json::Value user;
    // insert 和 login 函数的测试：
    // user["username"] = "xiaoming";
    user["username"] = "xiaohong";

    // user["password"] = "12345678";
    ut.insert(user);
    // ut.login(user);

    // select_by_name 函数的测试：
    // Json::Value name_select;
    // bool name_ret = ut.select_by_name("xiaoming", name_select);
    // std::string name_body;
    // json_util::serialize(name_select, name_body);
    // std::cout << name_body << std::endl;

    // select_by_id 函数的测试：
    // Json::Value id_select;
    // 上面只插入了一条数据，所以查询 id = 2 的时候是 nullptr
    // bool id_ret = ut.select_by_id(2, id_select);  
    // std::string id_body;
    // json_util::serialize(id_select, id_body);
    // std::cout << id_body << std::endl;

    // win 函数的测试：
    // bool win_ret = ut.win(1);

    // lose 函数的测试：
    // bool lose_ret = ut.lose(1);
}


void online_test(){
    online_manager om;
    wsserver_t::connection_ptr conn;
    uint64_t uid = 2;
    om.enter_game_hall(uid, conn);
    if(true == om.is_in_game_hall(uid)) DLOG("in game hall");
    else DLOG("no in game hall");
    om.exit_game_hall(uid);
    if(om.is_in_game_hall(uid) == true) DLOG("in game hall");
    else DLOG("no in game hall"); 


    uid= 1;
    om.enter_game_room(uid, conn);
    if(om.is_in_game_room(uid) == true) DLOG("in game room");
    else DLOG("no in game room");
    om.exit_game_room(uid);
    if(om.is_in_game_room(uid) == true) DLOG("in game room");
    else DLOG("no in game room"); 
}

void test_room_data(){
    uint64_t room_id = 10;
    user_table ut(HOST, USER, PASS, DBNAME, PORT);
    online_manager om;
    room r(room_id, &ut, &om);
}

// 下面的函数的函数名是不能为 room_manager 的哦，不然就和下面的 room_manager 类型冲突了。就变成一个递归函数调用了
// 就会又莫名其妙的报错信息的哦
void test_room_manager(){
    user_table ut(HOST, USER, PASS, DBNAME, PORT);
    online_manager om;
    room_manager rm(&ut, &om);
    room_ptr rp = rm.create_room(10, 20);
    return ;
}

void test_session_manager(){
    user_table ut(HOST, USER, PASS, DBNAME, PORT);
    online_manager om;
    room_manager rm(&ut, &om);
    room_ptr rp = rm.create_room(10, 20);
}



int main(void){
    // 启动服务器
    gobang_server server(HOST, USER, PASS, DBNAME, PORT);
    
    // 服务守护进程化
    // 1. 放在 start 后面是不会起作用的哦
    // 2. 守护进程化之后，好像匹配不了了，卡住了。就不实现了，这个bug不好改......
    // server.daemon(); 

    // 关闭守护进程操作步骤
    // netstat -anp | grep 端口号
    // kill -9 PID

    // 启动服务器
    server.start(8080);

    return 0;
}

